package com.one.group.admin.service.impl;

import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.one.group.admin.mapper.WorkAssignmentMapper;
import com.one.group.model.dto.UpdateRepairReportStatusDto;
import com.one.group.model.dto.WorkAssignmentAddDto;
import com.one.group.model.dto.WorkAssignmentQueryDto;
import com.one.group.model.dto.WorkAssignmentReceiptDto;
import com.one.group.model.dto.WorkAssignmentUpdateDto;
import com.one.group.model.entity.RepairReport;
import com.one.group.model.entity.WorkAssignment;
import com.one.group.model.vo.WorkAssignmentListVo;
import com.one.group.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.Map;

import java.util.Date;
import java.util.List;
import cn.hutool.core.convert.Convert;
import cn.dev33.satoken.stp.StpUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * @author 
 * @date 
 * @description 派工管理服务实现类
 */
@Service
@Slf4j
public class WorkAssignmentServiceImpl extends ServiceImpl<WorkAssignmentMapper, WorkAssignment> implements WorkAssignmentService {

    @Autowired
    private RepairReportService repairReportService;
    
    @Autowired
    private SpBillService spBillService;
    
    @Autowired
    private JdbcTemplate jdbcTemplate;

    // 获取租户ID的辅助方法
    private Long getCurrentTenantId() {
        Long tenantId = Convert.toLong(StpUtil.getExtra("tenant_id"));
        log.debug("当前租户ID: {}", tenantId);
        return tenantId;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateToCompleted(Long id) {
        if (id == null) {
            log.error("更新状态为已完成失败：派工单ID不能为空");
            return false;
        }
        
        // 根据ID查询派工单
        WorkAssignment targetAssignment = findById(id);
        if (targetAssignment == null) {
            log.error("未找到对应的派工单，ID: {}", id);
            return false;
        }
        
        // 验证租户权限
        if (!getCurrentTenantId().equals(targetAssignment.getTenantId())) {
            log.error("无权限操作该派工单，ID: {}", id);
            return false;
        }
        
        // 更新派工单状态为已完成
        targetAssignment.setCompletionStatus("已完成");
        targetAssignment.setCompletionTime(new Date());
        targetAssignment.setUpdateTime(new Date());
        
        boolean result = workAssignmentMapper.updateWorkAssignment(targetAssignment) > 0;
        
        if (result) {
            // 更新报修单状态为已完成
            UpdateRepairReportStatusDto updateStatusDto = new UpdateRepairReportStatusDto();
            updateStatusDto.setId(targetAssignment.getRepairReportId());
            updateStatusDto.setTenantId(getCurrentTenantId());
            updateStatusDto.setStatus("已完成");
            repairReportService.updateStatus(updateStatusDto);
            
            log.info("派工单状态更新为已完成成功，ID: {}", id);
        } else {
            log.error("派工单状态更新为已完成失败，ID: {}", id);
        }
        
        return result;
    }

    @Autowired
    private  WorkAssignmentMapper workAssignmentMapper;

    @Override
    public List<WorkAssignmentListVo> findWorkAssignmentByQueryDto(WorkAssignmentQueryDto workAssignmentQueryDto) {
        // 设置租户ID
        workAssignmentQueryDto.setTenantId(getCurrentTenantId());
        return workAssignmentMapper.findWorkAssignmentByQueryDto(workAssignmentQueryDto);
    }

    //派工并设置装修状态为已派工
    @Override
    public boolean insertWorkAssignment(WorkAssignmentAddDto workAssignmentAddDto) {
        WorkAssignment workAssignment = new WorkAssignment();
        BeanUtils.copyProperties(workAssignmentAddDto, workAssignment);
        
        // 设置默认值
        Date now = new Date();
        workAssignment.setCreateTime(now);
        workAssignment.setUpdateTime(now);
        workAssignment.setIsDeleted(0);
        workAssignment.setTenantId(getCurrentTenantId());

        boolean result = workAssignmentMapper.insertWorkAssignment(workAssignment) > 0;

        if (result) {
            // 修改装修状态为已派工
            UpdateRepairReportStatusDto updateRepairReportStatusDto = new UpdateRepairReportStatusDto();
            updateRepairReportStatusDto.setId(workAssignment.getRepairReportId());
            updateRepairReportStatusDto.setTenantId(getCurrentTenantId());
            updateRepairReportStatusDto.setStatus("已派工");
            repairReportService.updateStatus(updateRepairReportStatusDto);
        }else {
            log.error("插入派单失败");
        }
        return  result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateWorkAssignment(WorkAssignmentUpdateDto workAssignmentUpdateDto) {
        if (workAssignmentUpdateDto == null || workAssignmentUpdateDto.getId() == null) {
            log.error("更新派工单参数错误，ID不能为空");
            return false;
        }
        
        // 先查询原派工单信息，获取报修单ID
        WorkAssignment originalAssignment = findById(workAssignmentUpdateDto.getId());
        if (originalAssignment == null) {
            log.error("未找到对应的派工单，ID: {}", workAssignmentUpdateDto.getId());
            return false;
        }
        
        WorkAssignment workAssignment = new WorkAssignment();
        BeanUtils.copyProperties(workAssignmentUpdateDto, workAssignment);
        
        // 更新时间和租户ID
        workAssignment.setUpdateTime(new Date());
        workAssignment.setTenantId(getCurrentTenantId());
        
        boolean result = workAssignmentMapper.updateWorkAssignment(workAssignment) > 0;
        
        // 如果更新成功，且completionStatus字段被更新了，则同步更新报修单状态
        if (result && workAssignmentUpdateDto.getCompletionStatus() != null) {
            String repairStatus = "已完成";
            // 根据派工单类型和费用判断报修单状态
            if (workAssignmentUpdateDto.getType() != null && workAssignmentUpdateDto.getType() == 1 && 
                workAssignmentUpdateDto.getTotalFee() != null && workAssignmentUpdateDto.getTotalFee().compareTo(BigDecimal.ZERO) > 0) {
                repairStatus = "已完成并待付款";
            }
            
            // 更新报修单状态
            UpdateRepairReportStatusDto updateStatusDto = new UpdateRepairReportStatusDto();
            updateStatusDto.setId(originalAssignment.getRepairReportId());
            updateStatusDto.setTenantId(getCurrentTenantId());
            updateStatusDto.setStatus(repairStatus);
            repairReportService.updateStatus(updateStatusDto);
            
            log.info("派工单更新成功并同步更新报修单状态，派工单ID: {}, 报修单ID: {}, 状态: {}", 
                    workAssignmentUpdateDto.getId(), originalAssignment.getRepairReportId(), repairStatus);
        }
        
        return result;
    }

    @Override
    public boolean deleteWorkAssignment(Long id) {
        // 验证是否为当前租户的数据
        WorkAssignment existing = findById(id);
        if (existing == null || !getCurrentTenantId().equals(existing.getTenantId())) {
            return false;
        }
        return workAssignmentMapper.deleteWorkAssignment(id) > 0;
    }

    @Override
    public WorkAssignment findById(Long id) {
        // 查询后验证租户权限
        WorkAssignment assignment = workAssignmentMapper.findById(id);
        if (assignment != null && !getCurrentTenantId().equals(assignment.getTenantId())) {
            return null; // 无权限查看其他租户的数据
        }
        return assignment;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitReceipt(WorkAssignmentReceiptDto receiptDto) {
        if (receiptDto == null || receiptDto.getRepairReportId() == null) {
            log.error("回单参数错误，报修单ID不能为空");
            return false;
        }
        
        // 根据报修单ID直接查询派工单
        WorkAssignment targetAssignment = workAssignmentMapper.findByRepairReportId(
                receiptDto.getRepairReportId(), getCurrentTenantId());
        
        if (targetAssignment == null) {
            log.error("未找到对应的派工单，报修单ID: {}", receiptDto.getRepairReportId());
            return false;
        }
        
        // 验证租户权限
        if (!getCurrentTenantId().equals(targetAssignment.getTenantId())) {
            log.error("无权限操作该派工单，报修单ID: {}", receiptDto.getRepairReportId());
            return false;
        }
        
        // 更新派工单信息
        targetAssignment.setCompletionStatus(receiptDto.getHandlingSituation());
        targetAssignment.setCompletionTime(new Date());
        
        // 将处理情况和备注合并到assignmentNotes字段
        StringBuilder notesBuilder = new StringBuilder();
        if (targetAssignment.getAssignmentNotes() != null) {
            notesBuilder.append(targetAssignment.getAssignmentNotes()).append("\n");
        }
        notesBuilder.append("处理情况: ").append(receiptDto.getHandlingSituation()).append("\n");
        if (receiptDto.getRemarks() != null) {
            notesBuilder.append("备注: ").append(receiptDto.getRemarks());
        }
        targetAssignment.setAssignmentNotes(notesBuilder.toString());
        targetAssignment.setUpdateTime(new Date());
        
        boolean result = workAssignmentMapper.updateWorkAssignment(targetAssignment) > 0;
        
        if (result) {
            // 更新报修单状态
            UpdateRepairReportStatusDto updateStatusDto = new UpdateRepairReportStatusDto();
            updateStatusDto.setId(receiptDto.getRepairReportId());
            updateStatusDto.setTenantId(getCurrentTenantId());
            
            // 根据派工单类型判断是否需要收费
            String repairStatus = "已完成";
            if (targetAssignment.getType() != null && targetAssignment.getType() == 1 && 
                targetAssignment.getTotalFee() != null && targetAssignment.getTotalFee().compareTo(BigDecimal.ZERO) > 0) {
                repairStatus = "已完成并待付款";
                
                // 调用账单服务生成账单
                try {
                    // 1. 从报修单获取联系人信息
                    RepairReport repairReport = repairReportService.getById(receiptDto.getRepairReportId());
                    if (repairReport == null) {
                        log.error("未找到报修单信息，报修单ID: {}", receiptDto.getRepairReportId());
                        return result; // 或者根据业务需求决定是否继续
                    }
                    
                    // 2. 根据报修单的联系人和房间号信息查找业主
                    // 由于我们没有直接的查询方法，可以先获取租户ID
                    Long tenantId = getCurrentTenantId();
                    
                    // 3. 构建账单信息（这里暂时使用一个简化的实现，不直接调用myAdd方法）
                    // 实际应用中，应该根据联系人和房间号查询业主表，获取业主ID
                    Integer payerType = 1; // 1:业主 2:租房人员 3:客户
                    // 记录账单生成前的信息
                    log.info("待生成账单信息：报修单ID: {}, 联系人: {}, 联系电话: {}, 房间号: {}, 金额: {}", 
                            receiptDto.getRepairReportId(), 
                            repairReport.getContactPerson(), 
                            repairReport.getContactPhone(),
                            repairReport.getRoomNumber(),
                            targetAssignment.getTotalFee());
                    
                    // 4. 使用内部方法根据联系电话查询业主信息
                    Long ownerId = findOwnerIdByPhone(repairReport.getContactPhone(), tenantId);
                    if (ownerId != null) {
                        log.info("找到业主ID: {}，开始生成账单", ownerId);
                        
                        // 这里应该从报修单或收费标准系统中获取正确的收费标准ID
                        // 为简化实现，这里假设维修服务对应的收费标准ID为10
                        Long chargestandardId = 10L;
                        BigDecimal amount = targetAssignment.getTotalFee();
                        String billRemark = "派工维修服务费: " + receiptDto.getHandlingSituation();
                        
                        boolean billResult = spBillService.myAdd(payerType, ownerId, chargestandardId, amount, billRemark);
                        if (billResult) {
                            log.info("成功生成账单，报修单ID: {}, 业主ID: {}, 金额: {}", 
                                    receiptDto.getRepairReportId(), ownerId, amount);
                        } else {
                            log.error("生成账单失败，报修单ID: {}", receiptDto.getRepairReportId());
                        }
                    } else {
                        log.warn("未找到对应的业主信息，无法生成账单，联系电话: {}", repairReport.getContactPhone());
                    }
                } catch (Exception e) {
                    log.error("生成账单异常，报修单ID: {}", receiptDto.getRepairReportId(), e);
                    // 这里可以选择回滚事务或继续处理
                }
            }
            
            updateStatusDto.setStatus(repairStatus);
            repairReportService.updateStatus(updateStatusDto);
            
            log.info("派工回单成功，报修单ID: {}, 状态: {}", receiptDto.getRepairReportId(), repairStatus);
        } else {
            log.error("派工回单失败，更新派工单信息失败");
        }
        
        return result;
    }
    
    /**
     * 根据电话号码查询业主ID（内部方法，不修改业主管理业务）
     * @param phone 电话号码
     * @param tenantId 租户ID
     * @return 业主ID，如果未找到返回null
     */
    private Long findOwnerIdByPhone(String phone, Long tenantId) {
        if (phone == null || phone.trim().isEmpty()) {
            log.warn("查询业主时电话号码为空");
            return null;
        }
        
        try {
            String sql = "SELECT id FROM sp_owner WHERE phone = ? AND tenant_id = ? AND status = 1 LIMIT 1";
            Map<String, Object> result = jdbcTemplate.queryForMap(sql, phone.trim(), tenantId);
            return result != null ? Long.valueOf(result.get("id").toString()) : null;
        } catch (Exception e) {
            log.error("根据电话号码查询业主失败，电话: {}", phone, e);
            return null;
        }
    }
}